package protocol

import (
	"bytes"
	"encoding/binary"
	"net"
)

const (
	ConstHeader = "levi"	// header信息
	DataLength  = 4			// data length
)

func Packet(message []byte) []byte {
	return append(append([]byte(ConstHeader), IntToBytes(len(message))...), message...)
}

func Unpack(buffer []byte, readerChannel chan []byte) []byte {
	length := len(buffer)
	headerLength := len(ConstHeader)

	var i int
	for i = 0; i < length; i = i + 1 {
		if length < i+headerLength+DataLength {
			break
		}
		if string(buffer[i:i+headerLength]) == ConstHeader {
			messageLength := BytesToInt(buffer[i+headerLength : i+headerLength+DataLength])
			if length < i+headerLength+DataLength+messageLength {
				break
			}
			data := buffer[i+headerLength+DataLength : i+headerLength+DataLength+messageLength]
			readerChannel <- data

			i += headerLength + DataLength + messageLength - 1
		}
	}

	if i == length {
		return make([]byte, 0)
	}
	return buffer[i:]
}

func IntToBytes(n int) []byte {
	x := int32(n)

	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	return bytesBuffer.Bytes()
}

func BytesToInt(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)

	var x int32
	binary.Read(bytesBuffer, binary.BigEndian, &x)

	return int(x)
}

func Read(conn net.Conn, callback func(data string)) {

	tmpBuffer := make([]byte, 0)
	readerChannel := make(chan []byte, 16)

	go func() {
		for {
			select {
			case data := <-readerChannel:
				callback(string(data))
			}
		}
	}()

	buffer := make([]byte, 1024)

	for {
		b, err := conn.Read(buffer)
		if err != nil {
			return
		}

		tmpBuffer = Unpack(append(tmpBuffer, buffer[:b]...), readerChannel)
	}
}